package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.constants.message.NewsAutoScanConstants;
import com.heima.common.constants.message.NewsUpOrDownConstants;
import com.heima.common.constants.wemedia.WemediaConstants;
import com.heima.common.exception.CustException;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.threadlocal.WmThreadLocalUtils;
import com.heima.model.wemedia.dtos.NewsAuthDTO;
import com.heima.model.wemedia.dtos.WmNewsDTO;
import com.heima.model.wemedia.dtos.WmNewsPageReqDTO;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.vo.WmNewsVO;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.service.WmNewsMatetrialService;
import com.heima.wemedia.service.WmNewsService;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {
    @Value("${file.oss.web-site}")
    String webSite;

    @Override
    public ResponseResult findList(WmNewsPageReqDTO dto) {
        //校验数据合法性
        if (dto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        //将查询状态进行封装
        LambdaQueryWrapper<WmNews> wrapper = Wrappers.<WmNews>lambdaQuery();
        //判断状态
        if (dto.getStatus() != null){
            wrapper.eq(WmNews::getStatus, dto.getStatus());
        }
        //判断开始结束时间
        if (dto.getBeginPubDate() != null && dto.getEndPubDate() != null){
            wrapper.between(WmNews::getSubmitedTime, dto.getBeginPubDate(), dto.getEndPubDate());
        }
        //判断所属频道Id
        if (dto.getChannelId() != null){
            wrapper.eq(WmNews::getChannelId, dto.getChannelId());
        }
        //判断关键字
        if (dto.getKeyword() != null){
            wrapper.like(WmNews::getTitle, dto.getKeyword());
        }
        //初始化分页
        dto.checkParam();
        //封装分页
        Page page = new Page(dto.getPage(), dto.getSize());
        //根据分页查询
        IPage iPage = this.page(page, wrapper);
        PageResponseResult result = new PageResponseResult(dto.getPage(), dto.getSize(), page.getTotal(), iPage.getRecords());
        result.setHost(webSite);
        //封装结果返回
        return result;
    }


    @Autowired
    RabbitTemplate rabbitTemplate;
    /**
     * 创建文章提交
     * @param dto
     * @return
     */
    @Override
    public ResponseResult submit(WmNewsDTO dto) {
        //判断当前登录账户
        Integer userId = WmThreadLocalUtils.getUser().getId();
        if (userId == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //校验数据合法性
        if (dto.getContent() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE,"正文不能为空");
        }
        WmNews wmNews = new WmNews();
        //将图片集合转为字符串
        if (dto.getImages() != null){
            String images = imagesToString(dto.getImages());
            wmNews.setImages(images);
        }
        BeanUtils.copyProperties(dto, wmNews);
        //校验type属性
        if (wmNews.getType() == -1){
            wmNews.setType(null); //防止数据库异常
        }
        //设置文章创建的用户Id
        wmNews.setUserId(userId);
        //保存或者修改文章
        saveorUpdate(wmNews);
        //判断是否为草稿
        if (wmNews.getStatus() == 0){
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        //抽取文章中图片url路径
        List<String> contentImages = getUrlToString(dto.getContent());
        //判断图片集合是否有数据
        if (CollectionUtils.isNotEmpty(contentImages)){
            //将图片跟文章添加到关联表中
            insertNewsAndMaterial(contentImages,wmNews.getId(), WemediaConstants.WM_CONTENT_REFERENCE);
        }
        //保存封面与文章的关联关系
        saveRelateInfoForCover(contentImages,wmNews,dto);
        //将文章id发送到Mq调用自动审核
        rabbitTemplate.convertAndSend(NewsAutoScanConstants.WM_NEWS_AUTO_SCAN_QUEUE,wmNews.getId());
        log.info("调用文章自动审核,文章id{}",wmNews.getId());

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Autowired
    WmNewsMatetrialService wmNewsMatetrialService;

    /**
     * 根据id删除文章
     * @param id
     */
    @Override
    public ResponseResult deleteNews(Integer id) {
        //根据id查询文章状态
        WmNews wmNews = this.getById(id);
        if (WemediaConstants.WM_NEWS_PUBLISH_STATUS.equals(wmNews.getStatus())){
            //状态为9无法删除
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_ALLOW,"请先下架后操作");
        }
        //根据文章id,删除素材关联表
        LambdaQueryWrapper<WmNewsMaterial> wrapper = Wrappers.<WmNewsMaterial>lambdaQuery();
        wrapper.eq(WmNewsMaterial::getNewsId, id);
        wmNewsMatetrialService.remove(wrapper);
        //删除文章
        this.removeById(id);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 文章上下架
     * @param dto
     * @return
     */
    @Override
    public ResponseResult downOrUp(WmNewsDTO dto) {
        //校验参数合法性
        if (dto.getId()== null || dto.getEnable() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //根据文章id查询文章是否存在
        WmNews wmNews = this.getById(dto.getId());
        if (wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
        }
        //判断文章是否为发布状态
        if (wmNews.getStatus() != 9){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_ALLOW,"请发布后操作");
        }
        //修改状态
        wmNews.setEnable(dto.getEnable());
        this.updateById(wmNews);
        //通过mq修改配置信息
        if (wmNews.getArticleId() != null){
            if (wmNews.getEnable().equals(WemediaConstants.WM_NEWS_UP)){
                //上架请求发送
                rabbitTemplate.convertAndSend(NewsUpOrDownConstants.NEWS_UP_OR_DOWN_EXCHANGE,NewsUpOrDownConstants.NEWS_UP_ROUTE_KEY,wmNews.getArticleId());
            }else {
                //下架请求发送
                rabbitTemplate.convertAndSend(NewsUpOrDownConstants.NEWS_UP_OR_DOWN_EXCHANGE,NewsUpOrDownConstants.NEWS_DOWN_ROUTE_KEY,wmNews.getArticleId());
            }
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Autowired
    WmNewsMapper wmNewsMapper;
    /**
     * 审核列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult listVo(NewsAuthDTO dto) {
        //初始化分页
        dto.checkParam();
        //记录当前页
        int currentPage = dto.getPage();
        //设置起始页
        dto.setPage((dto.getPage()-1)*dto.getSize());
        if(StringUtils.isNotBlank(dto.getTitle())){
            dto.setTitle("%"+dto.getTitle()+"%");
        }

        //2.分页查询
        List<WmNewsVO> wmNewsVoList = wmNewsMapper.findListAndPage(dto);
        //统计多少条数据
        long count = wmNewsMapper.findListCount(dto);

        //3.结果返回
        ResponseResult result = new PageResponseResult(currentPage, dto.getSize(), count, wmNewsVoList);
        result.setHost(webSite);
        return result; }

    /**
     * 文章审核通过
     * @param dto
     * @return
     */
    @Override
    public ResponseResult newsPass(NewsAuthDTO dto) {
        //判断数据合法性
        if (dto.getId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //根据id查询文章状态
        WmNews wmNews = this.getById(dto.getId());
        //判断状态是为 3  => 待人工审核
        short stat = 3;
        if (wmNews.getStatus() != stat){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_ALLOW,"当前文章不是待人工审核状态");
        }
        //通过审核
        wmNews.setStatus(WemediaConstants.WM_NEWS_AUTH_PASS);
        this.updateById(wmNews);

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 文章人工驳回
     * @param dto
     * @return
     */
    @Override
    public ResponseResult newsFail(NewsAuthDTO dto) {
        //判断数据合法性
        if (dto.getId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //根据id查询文章状态
        WmNews wmNews = this.getById(dto.getId());
        //判断状态是为 3  => 待人工审核
        short stat = 3;
        if (wmNews.getStatus() != stat){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_ALLOW,"当前文章不是待人工审核状态");
        }
        //审核驳回
        wmNews.setStatus(WemediaConstants.WM_NEWS_AUTH_FAIL);
        //设置驳回理由
        wmNews.setReason(dto.getMsg());
        this.updateById(wmNews);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    /**
     * 保存封面与素材关联关系
     * @param contentImages     图片路径集合
     * @param wmNews            文章
     * @param dto               前端数据
     */
    private void saveRelateInfoForCover(List<String> contentImages, WmNews wmNews, WmNewsDTO dto) {
        //获取封面集合
        List<String> images = dto.getImages();
        //判断封面类型
        if (dto.getType().equals(WemediaConstants.WM_NEWS_TYPE_AUTO)){//设置自动配图
            //根据内容中的图片数量进行配置
            if (CollectionUtils.isEmpty(contentImages)){
                //设置无图
                wmNews.setType(WemediaConstants.WM_NEWS_NONE_IMAGE);
            }else if (contentImages.size()>0 && contentImages.size()<=2){
                //设置单图
                wmNews.setType(WemediaConstants.WM_NEWS_SINGLE_IMAGE);
                images = contentImages.stream().limit(1).collect(Collectors.toList());
            }else if (contentImages.size() >2){
                //设置3图
                wmNews.setType(WemediaConstants.WM_NEWS_MANY_IMAGE);
                images = contentImages.stream().limit(3).collect(Collectors.toList());

            }
            if (!CollectionUtils.isEmpty(images)){
                wmNews.setImages(imagesToString(images));
            }
            if (!CollectionUtils.isEmpty(images)){
                images = images.stream().map(url -> url.replaceAll(webSite, "")).distinct().collect(Collectors.toList());
            }
            //修改图片状态
            this.updateById(wmNews);
        }
        images = images.stream().map(url -> url.replaceAll(webSite, "")).distinct().collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(images)){
            insertNewsAndMaterial(images, wmNews.getId(), WemediaConstants.WM_IMAGE_REFERENCE);
        }
    }

    @Autowired
    WmMaterialMapper wmMaterialMapper;

    @Autowired
    WmNewsMaterialMapper wmNewsMaterialMapper;
    /**
     * 设置素材与文章关系关联
     * @param urls 图片名称集合
     * @param newsId    文章id
     * @param type    引用状态(0内容引用/1封面引用)
     */
    private void insertNewsAndMaterial(List<String> urls, Integer newsId, Short type) {
        //根据图片名称查询图片的id图片的数量
        List<Integer> ids = wmMaterialMapper.selectRelationsIds(urls, WmThreadLocalUtils.getUser().getId());
        //判断id是否为空或者查询的数量小于
        if (CollectionUtils.isEmpty(ids) || ids.size() < urls.size()){
            CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST,"相关素材不存在");
        }
        //保存素材与文章的关联关系
        wmNewsMaterialMapper.InsertNewsAndMaterial(ids,newsId,type);

    }

    /**
     * 将string字符串格式的图片转为集合
     * @param content
     * @return
     */
    private List<String> getUrlToString(String content) {
        List<Map> contentMap = JSONArray.parseArray(content, Map.class);
        return contentMap.stream()
                .filter(map -> "image".equals(map.get("type")))//找到type为image的属性
                .map(o -> (String)o.get("value"))//得到图路径
                .map(url -> url.replaceAll(webSite, ""))
                .distinct()
                .collect(Collectors.toList());
    }


    private void saveorUpdate(WmNews wmNews) {
        //判断当前是否有文章id
        if (wmNews.getId() == null){
            wmNews.setCreatedTime(new Date());
            wmNews.setSubmitedTime(new Date());
            save(wmNews);
        }else {
            //删除关联关系
            wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getNewsId, wmNews.getId()));
            updateById(wmNews);

        }
    }

    private String imagesToString(List<String> images) {
        return images.stream()
                .map(url -> url.replaceAll(webSite, ""))
                .collect(Collectors.joining(","));
    }
}